// SimpleMesh.cpp: implementation of the CSimpleMesh class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "SimpleMesh.h"

#pragma pack(4)
typedef struct _SMFHEADER
{
	DWORD			dwID;
	DWORD			dwType;
	DWORD			dwVertexCount;
	DWORD			dwFacesCount;
} SMFHEADER;
#pragma pack()

#define	SMF_ID		0x31464d53

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CSimpleMesh::CSimpleMesh() : m_pvbVertices( NULL ), m_pibIndices( NULL ), m_dwType( 0 ), m_dwVertexCount( 0 ), m_dwFacesCount( 0 )
{
}

CSimpleMesh::~CSimpleMesh()
{
	if( m_pvbVertices )
		m_pvbVertices->Release();

	if( m_pibIndices )
		m_pibIndices->Release();
}

BOOL CSimpleMesh::Load( PDIRECT3DDEVICE8 pDevice, TCHAR* name )
{
	ifstream				file;
	SMFHEADER				header;
	PVERTEX					pVertices;
	LPWORD					pIndices;

	file.open( name, ios::in|ios::binary );

	if( file.fail() )
		return FALSE;

	if( file.read( (LPBYTE)&header, sizeof(SMFHEADER) ).gcount() != sizeof( SMFHEADER ) )
		return FALSE;

	if( header.dwID != SMF_ID )
		return FALSE;

	m_dwVertexCount = header.dwVertexCount;
	m_dwFacesCount = header.dwFacesCount;

	if( FAILED( pDevice->CreateVertexBuffer( header.dwVertexCount*sizeof(VERTEX), 0, FVF_VERTEX, D3DPOOL_DEFAULT, &m_pvbVertices ) ) )
		return FALSE;

	if( FAILED( pDevice->CreateIndexBuffer( header.dwFacesCount*6, 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pibIndices ) ) )
		return FALSE;
	
	m_pvbVertices->Lock( 0, 0, (LPBYTE*)&pVertices, 0 );
	file.read( (LPBYTE)pVertices, header.dwVertexCount*sizeof(VERTEX) );		

	m_vCenter = he3d_CVector( 0, 0, 0 );

	for( DWORD i = 0 ; i < m_dwVertexCount ; i++ )
		m_vCenter += pVertices[i].m_vPos;

	m_vCenter = m_vCenter/(FLOAT)m_dwVertexCount;

	m_pvbVertices->Unlock();

	if( (DWORD)file.gcount() != header.dwVertexCount*sizeof(VERTEX) )
		return FALSE;

	m_pibIndices->Lock( 0, 0, (LPBYTE*)&pIndices, 0 );
	file.read( (LPBYTE)pIndices, header.dwFacesCount*6 );
	m_pibIndices->Unlock();

	if( (DWORD)file.gcount() != header.dwFacesCount*6 )
		return FALSE;

	file.close();

	return TRUE;
}

BOOL CSimpleMesh::Render( PDIRECT3DDEVICE8 pDevice )
{
	pDevice->SetVertexShader( FVF_VERTEX );
	pDevice->SetStreamSource( 0, m_pvbVertices, sizeof(VERTEX) );
	pDevice->SetIndices( m_pibIndices, 0 );

	pDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, m_dwVertexCount, 0, m_dwFacesCount );

	return TRUE;
}

he3d_CVector CSimpleMesh::GetCenter()
{
	return m_vCenter;
}

DWORD CSimpleMesh::GetFacesCount()
{
	return m_dwFacesCount;
}

DWORD CSimpleMesh::GetVertexCount()
{
	return m_dwVertexCount;
}

PDIRECT3DINDEXBUFFER8 CSimpleMesh::GetIndexBuffer()
{
	return m_pibIndices;
}

PDIRECT3DVERTEXBUFFER8 CSimpleMesh::GetVertexBuffer()
{
	return m_pvbVertices;
}

BOOL CSimpleMesh::LockMesh( LPBYTE* vertices, LPBYTE* indices )
{
	if( FAILED( m_pvbVertices->Lock( 0, 0, vertices, 0 ) ) )
		return FALSE;

	if( FAILED( m_pibIndices->Lock( 0, 0, indices, 0 ) ) )
		return FALSE;

	return TRUE;
}

BOOL CSimpleMesh::UnlockMesh()
{
	if( FAILED( m_pvbVertices->Unlock() ) )
		return FALSE;

	if( FAILED( m_pibIndices->Unlock() ) )
		return FALSE;

	return TRUE;
}

DWORD CSimpleMesh::GetVertexStride()
{
	return sizeof(VERTEX);
}

VOID CSimpleMesh::FlipNormals()
{
	PVERTEX					pVertices;

	m_pvbVertices->Lock( 0, 0, (LPBYTE*)&pVertices, 0 );

	for( DWORD i = 0 ; i < m_dwVertexCount ; i++ )
		pVertices[i].m_vN = -pVertices[i].m_vN;

	m_pvbVertices->Unlock();
}